package processor.images;

import java.awt.Component;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JOptionPane;
import variable.lazy.Lazy;
import variable.lazy.LazyValue;
import processor.MyException;

/**
 *
 * @author Shimu
 */
public class ImageProcessor {

    
    private ImageProcessor() {
    }

    private static final Lazy<Runtime> RUNTIME = new LazyValue<Runtime>(){
        @Override
        public Runtime initialize() {
            return Runtime.getRuntime();
        }
    };
    
    public static BufferedImage loadImage(File file) throws IOException {
        // Calculate the size of the image to see if we have enough memory to
        // load it
        // size in megabytes (MB)
        long size = file.getTotalSpace() / 1048576;
        if (size > RUNTIME.getValue().freeMemory() / 2) {
            throw new IOException("Not enough memory available to load the file");
        }

        try {
            BufferedImage img = ImageIO.read(file);

            if (img == null) {
                // No ImageReader could recognize the file format
                throw new IOException("Unsupported Image Format!");

            } 
            
            return img;

        } catch (OutOfMemoryError ex) {
            throw new IOException("Java ran out of memory!");
        }
    }
    
    /**
     * Save the given BufferedImage into the given image_path.extension.
     * Uses ImageIO.write(BufferedImage, String, File).
     * 
     * @param img the BufferedImage to be saved
     * @param image_path the path of the image file, including the picture
     * format extension (such as jpg, png, gif)
     * 
     * @throws MyException  
     */
    public static void saveImage(BufferedImage img, File file) 
            throws IOException {
        final String format = "jpg";
        if (!javax.imageio.ImageIO.write(img, format, file)) {
            throw new IOException(String.format(
                    "Unsupported saving format: %s!", format));
        }
    }
    
    public static BufferedImage toBufferedImage(Image img) {
        BufferedImage newImage = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = newImage.createGraphics();
        g.drawImage(img, 0, 0, null);
        
        return newImage;
    }
    /** 
     * Scales an image to fit into the given boundingWidth and boundingHeight,
     * while maintaining the aspect ratio of the original image. Uses
     * Image.getScaledInstance, hence given hints should be one of: 
     * Image.SCALE_AREA_AVERAGING, Image.SCALE_DEFAULT, Image.SCALE_FAST, 
     * Image.SCALE_REPLICATE, Image.SCALE_SMOOTH.
     * 
     * @param original
     * @param boundingWidth 
     * @param boundingHeight 
     * @param hints one of: Image.SCALE_AREA_AVERAGING, Image.SCALE_DEFAULT, 
     * Image.SCALE_FAST, Image.SCALE_REPLICATE, Image.SCALE_SMOOTH.
     * @return  
     */
    public static Image scaleToFit(Image original, 
            int boundingWidth, int boundingHeight, int hints) {
        int width, height;
        width = original.getWidth(null);
        height = original.getHeight(null);
        if ((original == null) || (width == 0) || (height == 0)) {
            return original;
        }
        
        double widthRatio, heightRatio, scaleRatio;
        widthRatio = ((double) boundingWidth) / ((double) width);
        heightRatio = ((double) boundingHeight) / ((double) height);
        scaleRatio = Math.min(widthRatio, heightRatio);
        
        int scaledWidth, scaledHeight;
        scaledWidth = (int) (width * scaleRatio);
        scaledHeight = (int) (height * scaleRatio);

        return original.getScaledInstance(scaledWidth, scaledHeight, hints);
    }
}
